Skip to main content

compio_driver\sys\pal\windows/
mod.rs

1use std::{fmt, io, ptr, task::Poll};
2
3pub use windows_sys::Win32::Networking::WinSock::CMSGHDR as CmsgHeader;
4use windows_sys::{
5    Win32::{
6        Foundation::{
7            ERROR_BROKEN_PIPE, ERROR_HANDLE_EOF, ERROR_IO_INCOMPLETE, ERROR_IO_PENDING,
8            ERROR_MORE_DATA, ERROR_NETNAME_DELETED, ERROR_NO_DATA, ERROR_NOT_FOUND,
9            ERROR_PIPE_CONNECTED, ERROR_PIPE_NOT_CONNECTED, GetLastError,
10        },
11        Networking::WinSock::{SIO_GET_EXTENSION_FUNCTION_POINTER, WSAIoctl},
12        System::IO::{CancelIoEx, OVERLAPPED},
13    },
14    core::GUID,
15};
16
17use crate::syscall;
18
19mod_use::mod_use![fd];
20
21pub mod reexport {
22    pub use super::Overlapped;
23}
24
25/// The overlapped struct we actually used for IOCP.
26#[repr(C)]
27pub struct Overlapped {
28    /// The base [`OVERLAPPED`].
29    pub base: OVERLAPPED,
30    /// The unique ID of created driver.
31    pub driver: RawFd,
32}
33
34impl fmt::Debug for Overlapped {
35    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
36        f.debug_struct("Overlapped")
37            .field("base", &"OVERLAPPED")
38            .field("driver", &self.driver)
39            .finish()
40    }
41}
42
43impl Overlapped {
44    pub(crate) fn new(driver: RawFd) -> Self {
45        Self {
46            base: unsafe { std::mem::zeroed() },
47            driver,
48        }
49    }
50}
51
52// SAFETY: neither field of `OVERLAPPED` is used
53unsafe impl Send for Overlapped {}
54unsafe impl Sync for Overlapped {}
55
56#[inline]
57pub fn winapi_result(transferred: u32) -> Poll<io::Result<usize>> {
58    let error = unsafe { GetLastError() };
59    assert_ne!(error, 0);
60    match error {
61        ERROR_IO_PENDING => Poll::Pending,
62        ERROR_IO_INCOMPLETE
63        | ERROR_NETNAME_DELETED
64        | ERROR_HANDLE_EOF
65        | ERROR_BROKEN_PIPE
66        | ERROR_PIPE_CONNECTED
67        | ERROR_PIPE_NOT_CONNECTED
68        | ERROR_NO_DATA
69        | ERROR_MORE_DATA => Poll::Ready(Ok(transferred as _)),
70        _ => Poll::Ready(Err(io::Error::from_raw_os_error(error as _))),
71    }
72}
73
74#[inline]
75pub fn win32_result(res: i32, transferred: u32) -> Poll<io::Result<usize>> {
76    if res == 0 {
77        winapi_result(transferred)
78    } else {
79        Poll::Ready(Ok(transferred as _))
80    }
81}
82
83#[inline]
84pub fn winsock_result(res: i32, transferred: u32) -> Poll<io::Result<usize>> {
85    if res != 0 {
86        winapi_result(transferred)
87    } else {
88        Poll::Ready(Ok(transferred as _))
89    }
90}
91
92#[inline]
93pub fn cancel(handle: RawFd, optr: *mut OVERLAPPED) -> io::Result<()> {
94    match syscall!(BOOL, CancelIoEx(handle as _, optr)) {
95        Ok(_) => Ok(()),
96        Err(e) => {
97            if e.raw_os_error() == Some(ERROR_NOT_FOUND as _) {
98                Ok(())
99            } else {
100                Err(e)
101            }
102        }
103    }
104}
105
106pub fn get_wsa_fn<F>(handle: RawFd, fguid: GUID) -> io::Result<Option<F>> {
107    let mut fptr = None;
108    let mut returned = 0;
109    syscall!(
110        SOCKET,
111        WSAIoctl(
112            handle as _,
113            SIO_GET_EXTENSION_FUNCTION_POINTER,
114            std::ptr::addr_of!(fguid).cast(),
115            std::mem::size_of_val(&fguid) as _,
116            std::ptr::addr_of_mut!(fptr).cast(),
117            std::mem::size_of::<F>() as _,
118            &mut returned,
119            ptr::null_mut(),
120            None,
121        )
122    )?;
123    Ok(fptr)
124}